package org.budo.mybatis.dao.statement.builder.creator;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;

import org.apache.ibatis.session.Configuration;
import org.budo.mybatis.dao.entity.configer.MyBatisDaoEntityConfiger;
import org.budo.mybatis.dao.statement.builder.impl.DefaultStatementBuilder;
import org.budo.support.lang.util.ReflectUtil;
import org.budo.support.lang.util.StringUtil;

/**
 * @author lmw
 */
public abstract class AbstractSaveStatementCreator extends AbstractStatementCreator {
    public AbstractSaveStatementCreator(Configuration configuration, DefaultStatementBuilder statementBuilder) {
        super(configuration, statementBuilder);
    }

    protected Map<String, String> insertColumnAndValues(MyBatisDaoEntityConfiger entityConfiger, Class<?> entityType, Boolean ignoreNull, String fieldNamePrefix) {
        Map<String, String> columnAndValues = new HashMap<String, String>();

        List<Field> fields = ReflectUtil.getAllFields(entityType);
        for (Field field : fields) {
            if (null != field.getAnnotation(Id.class)) {
                if (null == field.getAnnotation(GeneratedValue.class)) { // 未注解自增,则运行时判断,注解为自增则自增
                    if (ignoreNull) {
                        String columnsSql = "<if test=\"" + field.getName() + " != null\">" + field.getName() + ",</if>";
                        String valuesSql = "<if test=\"" + field.getName() + " != null\">#{" + fieldNamePrefix + field.getName() + "},</if>";
                        columnAndValues.put(columnsSql, valuesSql);
                        continue;
                    }
                    String columnsSql = field.getName();
                    String valuesSql = "#{" + fieldNamePrefix + field.getName() + "}";
                    columnAndValues.put(columnsSql, valuesSql);
                    continue;
                }
            }

            Column column = field.getAnnotation(Column.class);
            if (null != column && column.updatable()) {
                String columnName = this.getStatementBuilder().getEntityConfiger().getColumnName(field);

                if (ignoreNull) {
                    String columnsSql = "<if test=\"" + field.getName() + " != null\">" + columnName + ",</if>";
                    String valuesSql = "<if test=\"" + field.getName() + " != null\">#{" + field.getName() + "},</if>";
                    columnAndValues.put(columnsSql, valuesSql);
                } else {
                    String columnsSql = columnName;
                    String valuesSql = "#{" + fieldNamePrefix + field.getName() + "}";
                    columnAndValues.put(columnsSql, valuesSql);
                }

                continue;
            }

            if (null != field.getAnnotation(OneToOne.class) //
                    || null != field.getAnnotation(ManyToOne.class)) {
                String joinColumnName = this.getStatementBuilder().getEntityConfiger().getJoinColumnName(field);

                if (StringUtil.isEmpty(joinColumnName)) {
                    continue;
                }

                String idFieldName = entityConfiger.getIdFieldName(field.getType());

                if (ignoreNull) {
                    String columnsSql = "<if test=\"" + field.getName() + " != null and " + field.getName() + "." + idFieldName + " != null\">" + joinColumnName + ",</if>";
                    String valuesSql = "<if test=\"" + field.getName() + " != null and " + field.getName() + "." + idFieldName + " != null\">#{" + field.getName() + "." + idFieldName + "},</if>";
                    columnAndValues.put(columnsSql, valuesSql);
                } else {
                    String columnsSql = joinColumnName;
                    String valuesSql = "#{" + fieldNamePrefix + field.getName() + "." + idFieldName + "}";
                    columnAndValues.put(columnsSql, valuesSql);
                }
                continue;
            }
        }
        return columnAndValues;
    }
}
